package mgorm

import (
	"fmt"
	"gitee.com/dreamwood/jxgo/v1/mgorm/expr"
	"go.mongodb.org/mongo-driver/bson"
)

// PPL 是Pipeline 的缩写，是MongoDB提供的一种查询语言，用于对数据进行过滤、聚合和排序。
type PPL struct {
	Stages []bson.D `json:"stages"`
	Dumps  []string
}

func NewPPL() *PPL {
	return &PPL{
		Stages: make([]bson.D, 0),
	}
}
func (this *PPL) Get() []bson.D {
	ppl := make([]bson.D, 0)
	for _, stage := range this.Stages {
		ppl = append(ppl, stage)
	}
	return ppl
}

func (this *PPL) Add(value bson.D) *PPL {
	this.Stages = append(this.Stages, value)
	return this
}

func (this *PPL) AddMatch(value bson.D) bson.D {
	match := bson.D{
		{
			Key:   expr.MATCH_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, match)
	return match
}
func (this *PPL) AddGroup(value bson.D) bson.D {
	group := bson.D{
		{
			Key:   expr.GROUP_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, group)
	return group
}
func (this *PPL) AddSort(value bson.D) bson.D {
	if len(value) == 0 {
		return nil
	}
	sort := bson.D{
		{
			Key:   expr.SORT_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, sort)
	return sort
}
func (this *PPL) AddLimit(value int64) bson.D {
	limit := bson.D{
		{
			Key:   expr.LIMIT_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, limit)
	return limit
}
func (this *PPL) AddSkip(value int64) bson.D {
	skip := bson.D{
		{
			Key:   expr.SKIP_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, skip)
	return skip
}
func (this *PPL) AddUnwind(value string) bson.D {
	unwind := bson.D{
		{
			expr.UNWIND_C, fmt.Sprintf("$%s", value),
		},
	}
	this.Stages = append(this.Stages, unwind)
	return unwind
}
func (this *PPL) AddLookup(from, as, localField, foreignField string, pipeline ...bson.D) bson.D {
	if pipeline == nil {
		pipeline = make([]bson.D, 0)
	}
	lookup := bson.D{
		{
			expr.LOOKUP_C,
			bson.D{
				{"from", from},
				{"localField", localField},
				{"foreignField", foreignField},
				{"as", as},
				{"pipeline", pipeline},
			},
		},
	}
	this.Stages = append(this.Stages, lookup)
	return lookup
}
func (this *PPL) AddProject(value bson.D) bson.D {
	project := bson.D{
		{
			Key:   expr.PROJECT_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, project)
	return project
}
func (this *PPL) AddOut(value string) bson.D {
	out := bson.D{
		{
			Key:   expr.OUT_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, out)
	return out
}
func (this *PPL) AddReduce(value bson.D) bson.D {
	reduce := bson.D{
		{
			Key:   expr.REDUCE_C,
			Value: value,
		},
	}
	this.Stages = append(this.Stages, reduce)
	return reduce
}

type Stage struct {
	Name string
}

func NewStage() *Stage {
	return &Stage{}
}
